package edu.westga.cs3152.wordmojo;

import java.util.ArrayList;

 /**
  * The Gameboard class kepps track of the elements of the game
  * (the board, the player's letters)
  * 
  * @author Lewis Williams
  * @version 2011.5.3
  *
  */
public class GameBoard {
	private Letter [][] theBoard;
	private Letter [] playerLetters;
	private final int BOARD_ROWS = 9;
	private final int BOARD_COLUMNS = 9;
	private Letter selectedTile = new Letter();
	private boolean tileSelected = false;
	private int turn = 0;
	private int lettersOnTheBoard = 0;
	private int numberOfWordsOnBoard = 0;
	private int lengthOfAllPlayedWords = 0;
	private boolean singleLetterError = false;
	
	private ArrayList<String> suggestedWords = new ArrayList<String>();

	private BoardParser boardParser;
	private SpellChecker spellChecker;
	private Dictionary letterProducer = new Dictionary("words.txt");
	public boolean showHint = false;
	public boolean hintUsed = false;
	
	public GameBoard() {
    	theBoard = new Letter[BOARD_ROWS][BOARD_COLUMNS];
    	playerLetters = new Letter[7];
    	setUpBlankBoard();
    	generatePlayerLetters();
    }

	/**
	 * Sets up the blank board at the start of the game
	 */
	private void setUpBlankBoard() {
		for(int row = 0; row < BOARD_ROWS; row++){
    		for(int column = 0; column < BOARD_COLUMNS; column++){
    			Letter letter = new Letter();
    			theBoard[row][column] = letter;
    		}
    	}
	}
	
	/**
	 * Generates the player's letters.
	 */
	private void generatePlayerLetters(){
		turn++;
		suggestedWords.clear();
		String firstWord = letterProducer.returnThreeLetterWord();
		suggestedWords.add(firstWord);
		
		String secondWord = letterProducer.returnFourLetterWord();
		suggestedWords.add(secondWord);
		
		String word = firstWord.toUpperCase() + secondWord.toUpperCase();
		
		int[] randomizer = {1,3,6,5,2,0,4};
		for(int i = 0; i < 7; i++){
			Letter letter = new Letter(word.charAt(randomizer[i]));
			letter.setOnBoard(false);
			playerLetters[i] = letter;
		}
	}
		

/**
 * Controls whether or not a tile can be moved or selected.
 * 
 * @param source
 * 			The letter that was clicked
 */
	public void selectOrDropTile(Object source) {
		if(tileSelected == false){
			if(((Letter) source).getLetter() != '@' && ((Letter) source).isMovable() == true){
				selectedTile = (Letter) source;
				tileSelected = true;
			}
		}
		else if(tileSelected == true){
			if(((Letter) source).getLetter() == '@'){
				((Letter) source).setLetter(selectedTile.getLetter());
				selectedTile.setLetter('@');
				tileSelected = false;
			}
			else if(((Letter) source).getLetter() != '@' && ((Letter) source).isMovable() == true){
				selectedTile = (Letter) source;
			}
		}
		countLettersOnTheBoard();
	}
	
	/**
	 * Decides if the player's letter placement is valid and starts a new turn.
	 */
	public void evaluateBoard() {
		boardParser = new BoardParser(this);
		spellChecker = new SpellChecker();
		int result = spellChecker.checkSpelling(boardParser.getAttemptedWords());
		System.out.println(result);

		if(singleLetterError == true){
			result = 0;
		}
		singleLetterError = false;
		lengthOfAllPlayedWords = spellChecker.getLengthOfAllWords();
		if(result == -1){
			removeInvalidWords();
			generatePlayerLetters();
		}
		else if(result == 0){
			removeInvalidWords();
			generatePlayerLetters();
		}
		else if(numberOfWordsOnBoard > 1 && lettersOnTheBoard >= result){
			removeInvalidWords();
			generatePlayerLetters();
		}
		else{
			lockLettersOnBoard();
			generatePlayerLetters();
		}
		
		if(hintUsed == true){
			showHint = false;
		}
	}
	
	/**
	 * Removes all invalid words from the board
	 */
	private void removeInvalidWords(){
		for(int row = 0; row < BOARD_ROWS; row++){
    		for(int column = 0; column < BOARD_COLUMNS; column++){
    			if(theBoard[row][column].isMovable()){
    				theBoard[row][column].setLetter('@');
    			}
    		}
    	}		
	}
	
	/**
	 * Locks all letters on the board that were movable.
	 */
	private void lockLettersOnBoard(){
		for(int row = 0; row < BOARD_ROWS; row++){
    		for(int column = 0; column < BOARD_COLUMNS; column++){
    			if(theBoard[row][column].isMovable() && theBoard[row][column].getLetter() != '@'){
    				theBoard[row][column].setMovable(false);
    			}
    		}
    	}
		selectedTile = new Letter();
		tileSelected = false;
	}

	public ArrayList<String> returnSuggestWords() {
		return suggestedWords;
	}
	
	/**
	 * Shows the hint if it is available.
	 */
	public void showHint(){
		if(hintUsed == false){
			showHint = true;
		}
		hintUsed = true;
	}

	/////////////////////////////////////////////////////////////////////////////////
	//////////////////////Getters, Setters, and Private Methods//////////////////////
	/////////////////////////////////////////////////////////////////////////////////
	
	public Letter getPiece(int row, int column) {
    	Letter letter;
		if(row > -1 && row < 9 && column > -1 && column < 9){
    		letter = theBoard[row][column];
    	}
		else{
			letter = new Letter('@');
		}
		return letter;
    }
	
	public int getBOARD_ROWS() {
		return BOARD_ROWS;
	}

	public int getBOARD_COLUMNS() {
		return BOARD_COLUMNS;
	}
	
	public Letter[] getPlayerLetters() {
		return playerLetters;
	}
	
	public Letter getSelectedTile() {
		return selectedTile;
	}
	
	public int getTurn() {
		return turn;
	}
	
	private void countLettersOnTheBoard(){
		lettersOnTheBoard = 0;
		for(int row = 0; row < BOARD_ROWS; row++){
    		for(int column = 0; column < BOARD_COLUMNS; column++){
    			if(theBoard[row][column].getLetter() != '@'){
    				lettersOnTheBoard++;
    			}
    		}
    	}
	}
	
	public void setLengthOfAllPlayedWords(int lengthOfAllPlayedWords) {
		this.lengthOfAllPlayedWords = lengthOfAllPlayedWords;
	}
	
	public void setNumberOfWordsOnBoard(int numberOfWordsOnBoard) {
		this.numberOfWordsOnBoard = numberOfWordsOnBoard;
	}
	
	public void setSingleLetterError(boolean singleLetterError) {
		this.singleLetterError = singleLetterError;
	}
	
	public ArrayList<String> getSuggestedWords() {
		return suggestedWords;
	}

}
